﻿using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace StandardManager.EntityCode
{
    public class ExportExcel
    {
        private static Dictionary<TreeNode, int> treeNodeTag=new Dictionary<TreeNode, int>();
        public static void ExportTreeViewToExcel(TreeView treeView, string output,List<TreeNode> filterNodes=null)
        {
            treeNodeTag.Clear();
            using (var package = new ExcelPackage())
            {
                var worksheet = package.Workbook.Worksheets.Add("TreeView Data");

                int maxDepth = GetTreeViewDepth(treeView.Nodes);
                CreateHeader(maxDepth, worksheet);
                int row = 3;
                UpdateTreeView(treeView.Nodes);

                if (filterNodes == null)
                {
                    filterNodes= new List<TreeNode>();
                    for(var k=0;k< treeView.Nodes.Count;k++)
                    {
                        filterNodes.Add(treeView.Nodes[k]);
                    }
                }

                ExportNode(filterNodes, worksheet, ref row);
                UpdateBlankCells(worksheet);

                // 保存 Excel 文件
                var fileInfo = new FileInfo(output);
                package.SaveAs(fileInfo);
            }
        }

        private static void UpdateBlankCells(ExcelWorksheet worksheet)
        {
            int rows = worksheet.Dimension.End.Row;
            int cols = worksheet.Dimension.End.Column;

            for (int row = 1; row <= rows; row++)
            {
                for (int col = 1; col <= cols; col++)
                {                    
                    ExcelRange cell = worksheet.Cells[row, col];                    
                    if (IsCellBlank(cell))
                    {
                        worksheet.Cells[row, col].Value = "/";
                    }
                }
            }
        }

        /// <summary>
        /// 检查单元格是否为空白
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <returns>是否为空白</returns>
        private static bool IsCellBlank(ExcelRange cell)
        {
            if (cell.Value == null)
            {
                return true;
            }

            if (cell.Value is string str && string.IsNullOrWhiteSpace(str))
            {
                return true;
            }

            return false;
        }

        private static void CreateHeader(int maxDepth, ExcelWorksheet worksheet)
        {
            for (int i = 0; i < maxDepth; i++)
            {
                worksheet.Cells[1, i * 2 + 1].Value = $"{i + 1}级类";
                worksheet.Cells[1, i * 2 + 1, 1, i * 2 + 2].Merge = true;
                worksheet.Cells[2, i * 2 + 1].Value = "名称";
                worksheet.Cells[2, i * 2 + 2].Value = "代码";                
            }
        }

        private static int GetTreeViewDepth(TreeNodeCollection nodes)
        {
            if (nodes == null || nodes.Count == 0)
            {
                return 0;
            }

            int maxDepth = 0;

            foreach (TreeNode node in nodes)
            {
                // 递归计算当前节点的最大深度
                int currentDepth = 1 + GetTreeViewDepth(node.Nodes);
                // 更新最大深度
                if (currentDepth > maxDepth)
                {
                    maxDepth = currentDepth;
                }
            }

            return maxDepth;
        }

        public static void UpdateTreeView(TreeNodeCollection nodes)
        {
            foreach (TreeNode node in nodes)
            {
                UpdateLeafNodeCount(node);
            }
        }

        public static void UpdateLeafNodeCount(TreeNode node)
        {
            // 计算当前节点下所有叶子节点的数量
            int leafCount = CountLeafNodes(node);
            treeNodeTag.Add(node, leafCount);

            // 递归更新子节点的Tag
            foreach (TreeNode childNode in node.Nodes)
            {
                UpdateLeafNodeCount(childNode);
            }
        }

        private static int CountLeafNodes(TreeNode node)
        {
            if (node.Nodes.Count == 0)
            {
                return 1;
            }

            // 递归计算所有子节点的叶子节点数量
            int leafCount = 0;
            foreach (TreeNode childNode in node.Nodes)
            {
                leafCount += CountLeafNodes(childNode);
            }

            return leafCount;
        }

        private static void ExportNode(List<TreeNode> nodes, ExcelWorksheet worksheet, ref int row, int level = 0, string code = "")
        {
            foreach (TreeNode node in nodes)
            {
                // 拆分单元格名称内容Code(Name)
                int left = node.Text.IndexOf("(");
                int right = node.Text.IndexOf(")");
                string childCode = code + node.Text.Substring(0, left);
                string name = node.Text.Substring(left + 1, right - left - 1);
                worksheet.Cells[row, level + 1].Value = name;
                worksheet.Cells[row, level + 2].Value = childCode;

                if (node.Nodes.Count > 0)
                {
                    var tnTag = treeNodeTag[node];
                    // 合并当前单元格
                    worksheet.Cells[row, level + 1, row + (int)tnTag - 1, level + 1].Merge = true;
                    worksheet.Cells[row, level + 2, row + (int)tnTag - 1, level + 2].Merge = true;
                }
                else
                {
                    row++;
                }

                if (node.Nodes.Count > 0)
                {
                    List<TreeNode> childrenNodes=TncToList(node);
                    ExportNode(childrenNodes, worksheet, ref row, level + 2, childCode);
                }
            }
        }

        private static List<TreeNode> TncToList(TreeNode tn)
        {
            var filterNodes = new List<TreeNode>();
            for (var k = 0; k < tn.Nodes.Count; k++)
            {
                filterNodes.Add(tn.Nodes[k]);
            }
            return filterNodes;
        }
    }
}
